package com.wit.witmg.config;

import com.wit.witmg.entity.DeviceSession;
import com.wit.witmg.entity.TMonitDust;
import com.wit.witmg.entity.TMonitep;
import com.wit.witmg.service.ITMonitDustService;
import com.wit.witmg.service.ITMonitepService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.*;

@Component
@RequiredArgsConstructor
public class MonitepTcpServer implements CommandLineRunner, DisposableBean {
    //电耗监测记录TCP服务器
    final ITMonitepService monitepService;

    // 配置参数
    private static final int PORT = 2406;
    private static final int MAX_THREADS = 100;
    private static final int HEARTBEAT_INTERVAL = 30; // 心跳间隔(秒)
    private static final int RECONNECT_WAIT_TIME = 5000; // 客户端重连等待时间(毫秒)

    // 连接管理
    private final ConcurrentMap<String, DeviceSession> activeSessions = new ConcurrentHashMap<>();
    private ServerSocket serverSocket;
    private ExecutorService threadPool;
    private ScheduledExecutorService scheduler;
    private volatile boolean isRunning = true;

    @Override
    public void run(String... args) throws Exception {
        startTcpServer();
    }

    @Override
    public void destroy() throws Exception {
        // Spring容器关闭时优雅停止服务
        stopTcpServer();
    }

    private void startTcpServer() {
        threadPool = Executors.newFixedThreadPool(MAX_THREADS);
        scheduler = Executors.newScheduledThreadPool(1);

        try {
            serverSocket = new ServerSocket(PORT);
            System.out.printf("TCP服务器已启动，监听端口: %d\n", PORT);

            // 独立线程处理客户端连接
            new Thread(() -> {
                while (isRunning) {
                    try {
                        Socket clientSocket = serverSocket.accept();
                        threadPool.execute(() -> handleClient(clientSocket));
                    } catch (IOException e) {
                        if (isRunning) {
                            System.err.println("接受客户端连接异常: " + e.getMessage());
                        }
                    }
                }
            }).start();

//            startHeartbeatCheck();
        } catch (IOException e) {
            System.err.println("TCP服务器启动失败: " + e.getMessage());
            throw new RuntimeException("TCP服务器启动失败", e);
        }
    }

    private void stopTcpServer() {
        isRunning = false;

        // 关闭所有客户端连接
        activeSessions.forEach((id, session) -> {
            try {
                session.getSocket().close();
            } catch (IOException e) {
                System.err.println("关闭客户端连接异常: " + e.getMessage());
            }
        });
        activeSessions.clear();

        // 关闭线程池
        if (threadPool != null) {
            threadPool.shutdownNow();
        }
        if (scheduler != null) {
            scheduler.shutdownNow();
        }

        // 关闭服务器Socket
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                System.err.println("关闭服务器Socket异常: " + e.getMessage());
            }
        }

        System.out.println("TCP服务器已停止");
    }

    private void handleClient(Socket socket) {
        String clientIp = socket.getInetAddress().getHostAddress();
        System.out.printf("新连接来自: %s\n", clientIp);
        try (InputStream in = socket.getInputStream();
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {

            byte[] buffer = new byte[1024]; // 缓冲区大小可根据实际情况调整
            int bytesRead;

            while ((bytesRead = in.read(buffer)) != -1) {
                String receivedData = new String(buffer, 0, bytesRead).trim();
//                System.out.println("收到数据（HEX）: " + bytesToHex(buffer, bytesRead));
                System.out.println("收到数据（ASCII）: " + receivedData);

                // 检查是否是特定指令 "108B00008B16"
                if (receivedData.contains("108B00008B16")) {
                    // 回复 "1049FFFF4716"（按需调整编码方式）
                    out.println("1049FFFF4716\r\n");
//                    out.flush();
                    System.out.println("发送响应（HEX）: 1049FFFF4716");
                    continue; // 跳过后续处理
                }

                // 其他数据尝试解析并存入数据库
                try {
                    TMonitep t = parseString(receivedData);
                    if (t != null) {
                        boolean bl= monitepService.save(t);
                        if(bl) {
                            System.out.println("数据已保存到数据库");
                            if (t.getPid() != null && t.getPid() > 0) {
                                String sbid = t.getPid().toString() + t.getSid();
                                DeviceSession session = new DeviceSession(Integer.parseInt(sbid), socket, out);
                                activeSessions.put(sbid, session);
                                monitepService.addConnection(sbid, session);
                                monitepService.handleDeviceMessage(sbid, receivedData);
                            }
                        }
                    }

                    // 发送通用响应 "1000FFFFFE"（按需调整编码方式）
//                    byte[] generalResponse = hexStringToByteArray("1000FFFFFE");
                    out.println("1000FFFFFE\r\n");
                    System.out.println("发送通用响应（HEX）: 1000FFFFFE");
                } catch (Exception e) {
                    System.err.println("数据处理异常: " + e.getMessage());
                }
            }
        } catch (IOException e) {
            System.err.println("客户端处理异常: " + e.getMessage());
        }

    }


    public TMonitep parseString(String input) {
        if (input == null || input.isEmpty()) {
            return null;
        }
        TMonitep t = new TMonitep();
        String[] strs= input.split("\\|");
        t.setPid(Long.parseLong(strs[0],16));
        t.setSid(Long.parseLong(strs[1],16));
        t.setEp((int)(get10valueSimple(strs[2])*100));
        t.setSc(Integer.parseInt(strs[3],16));
        t.setPf(getInt(strs[4]));
        String pv= strs[5];
        t.setPa(getInt(pv.substring(0,8)));
        t.setPb(getInt(pv.substring(8,16)));
        t.setPc(getInt(pv.substring(16)));
        t.setDate(System.currentTimeMillis()/1000);
        return t;
    }

    private float get10valueSimple(String hex) {
        int intBits = (int) Long.parseLong(hex, 16);
        return Float.intBitsToFloat(intBits);
    }

    private int getInt(String hex) {
        return (int) get10valueSimple(hex);
    }

}